# -*- coding: utf-8 -*-
import collections
import datetime
import hashlib
import json
import time

import redis
import requests
from django.contrib.auth.decorators import login_required
from django.http import JsonResponse, HttpResponse
from django.shortcuts import render, get_object_or_404
from django.views.decorators.csrf import csrf_exempt

from dwebsocket.decorators import accept_websocket
from pkg import models
from pkg.apk import get_apk_list, unzip_apk, parser_manifest, get_apk_md5
from pkg.models import TestDetail,YDGame
from pkg.send_mail import send_mail

from sdklog.settings import APK_DIR
# from pkg.yd_game import yd_game, yd_game_projectid


# redis连接池类，返回一个redis链接



class RedisPool:
    def __init__(self, host="127.0.0.1", port=6379, db=0):
        self.host = host
        self.port = port
        self.db = db

    def redis_connect(self):
        pool = redis.ConnectionPool(host=self.host, port=self.port, db=self.db)
        return redis.StrictRedis(connection_pool=pool)


P1 = RedisPool("127.0.0.1", 6379, 1)
P2 = RedisPool("127.0.0.1", 6379, 2)


def index(request):
    return render(request, 'pkg/index.html')


@login_required
def jm(request, client_id=None, logs=None):
    # 获取游戏类型(android,iOS)，根据游戏类型显示不同的页面
    game_type = request.GET.get("game_type", "android")
    case_info = None
    if game_type == "android":
        index_html = "pkg/jm_android.html"
    else:
        game_type = "iOS"
        index_html = "pkg/jm_iOS.html"

    # 获取APK列表
    apk_list = get_apk_list(APK_DIR)
    # 地址中传入client_id时
    if client_id:
        game = get_object_or_404(models.Game, client_id=client_id)
        game_type = game.game_type
        test_details = game.testdetail_set.all()

        # 地址中传入logs时
        if logs:
            history_logs = []
            if game_type == "android":
                log_html = "pkg/jm_android_logs.html"
            else:
                log_html = "pkg/jm_iOS_logs.html"
            for history_log in test_details:
                history_log.case_info = json.loads(history_log.case_info)
                history_logs.append(history_log)
            return render(request, log_html, locals())
        else:
            if game_type == "android":
                index_html = "pkg/jm_android.html"
            else:
                index_html = "pkg/jm_iOS.html"
            if len(test_details) > 0:
                game_log = test_details[0]
                case_info = json.loads(game_log.case_info)
    # 获取游戏列表
    games_list = models.Game.objects.filter(game_type=game_type)
    games = {}
    for game_item in games_list:
        games[game_item.client_id] = game_item.name
    return render(request, index_html, locals())

def get_yd_info(client_id):
    """
    获取源点配置，根据client_id 返回是否源点，以及project_id
    :param client_id:
    :return:
    """
    yd_game = False
    project_id=None
    if YDGame.objects.filter(game__client_id=client_id).exists():
        yd_game=True
        project_id = YDGame.objects.filter(game__client_id=client_id).values('project_id__project_id')[0].get('project_id__project_id')
    return yd_game,project_id

def get_game_info(request, client_id):
    """ 获取游戏信息，最近一次用例结果 """
    game = get_object_or_404(models.Game, client_id=client_id)
    test_details = game.testdetail_set.all()
    last_log = None
    if len(test_details) > 0:
        log_obj = test_details[0]
        last_log = {
            "log_id": log_obj.id,
            "appver": log_obj.appver,
            "pt_type": log_obj.pt_type,
            "suid": log_obj.suid,
            "sy_sdk": log_obj.sy_sdk,
            "fn_sdk": log_obj.fn_sdk,
            "vcode": log_obj.vcode,
            "recharge": log_obj.recharge,
            "package": log_obj.package,
            "md5": log_obj.md5,
            "device_id": log_obj.device_id,
            "plat_channel": log_obj.plat_channel,
            "sy_channel": log_obj.sy_channel,
            "case_info": json.loads(log_obj.case_info),
            "result": log_obj.result,
            "add_date": log_obj.add_date,
            "test_ext": log_obj.test_ext,
            "modify_date": log_obj.modify_date,
            "creator": log_obj.creator,
        }
    r = P1.redis_connect()
    key_flag = client_id + "_CHANGE_AUTO_LOGIN"
    # 获取游戏新玩家模式开关
    new_user_setting = "off"
    if r.exists(key_flag):
        if int(r.get(key_flag)) == 1:
            new_user_setting = "on"

    # yd_flag = False
    # if client_id in yd_game: yd_flag = True
    yd_flag,project_id=get_yd_info(client_id)

    ret = {
        "game_id": game.id,
        "client_id": client_id,
        "game_type": game.game_type,
        "name": game.name,
        "game_ext": game.game_ext,
        "case_log": last_log,
        "yd_flag": yd_flag,
        "new_user_setting": new_user_setting

    }

    return JsonResponse(ret)


def update_game_ext(request):
    client_id = request.POST.get('client_id')
    game_ext = request.POST.get('game_ext')
    game = get_object_or_404(models.Game, client_id=client_id)
    game.game_ext = game_ext
    game.save()
    ret = {
        "msg": "save success,game_id:%s" % client_id,
        "client_id": client_id,
        "game_ext": game_ext
    }
    return JsonResponse(ret)


def del_game_log(request, log_id):
    log = get_object_or_404(models.TestDetail, pk=log_id)
    log.delete()
    ret = {
        "msg": "delete success,log_id:%s" % log_id
    }
    return JsonResponse(ret)


@csrf_exempt
def add_game_log(request, client_id):
    """
    添加测试用例数据
    :param request:
    :param client_id:
    :return:
    """
    if request.method == 'POST':
        case_info = {
            "open_game": {
                "dl": request.POST.get('open_game_dl'),
                "ly": request.POST.get('open_game_ly'),
                "yd": request.POST.get('open_game_yd'),
                "ext": request.POST.get('open_game_ext'),
            },
            "before_login": {
                "dl": request.POST.get('before_login_dl'),
                "ly": request.POST.get('before_login_ly'),
                "ext": request.POST.get('before_login_ext')},
            "regist": {
                "dl": request.POST.get('regist_dl'),
                "ext": request.POST.get('regist_ext'),
                "yd": request.POST.get('regist_yd'),
                "yd_ext": request.POST.get('regist_yd_ext'),
            },
            "login": {
                "yd": request.POST.get('login_yd'),
                "ext": request.POST.get('login_ext'),
            },
            "after_login": {
                "dl": request.POST.get('after_login_dl'),
                "ly": request.POST.get('after_login_ly'),
                "ext": request.POST.get('after_login_ext'),
            },
            "select_server": {
                "dl": request.POST.get('select_server_dl'),
                "ly": request.POST.get('select_server_ly'),
                "yd": request.POST.get('select_server_yd'),
                "ext": request.POST.get('select_server_ext'),
            },
            "pay_num": {
                "dl": request.POST.get('pay_num_dl'),
                "ext": request.POST.get('pay_num_ext')
            },
            "recharge": {
                "dl": request.POST.get('recharge_dl'),
                "ly": request.POST.get('recharge_ly'),
                "ext": request.POST.get('recharge_ext'),
                "yd": request.POST.get('recharge_yd'),
            },
            "online": {
                "dl": request.POST.get('online_dl'),
                "ly": request.POST.get('online_ly'),
                "ext": request.POST.get('online_ext')
            },
            "create_role": {
                "dl": request.POST.get('create_role_dl'),
                "ly": request.POST.get('create_role_ly'),
                "yd": request.POST.get('create_role_yd'),
                "ext": request.POST.get('create_role_ext'),
            },
            "level": {
                "dl": request.POST.get('level_dl'),
                "ly": request.POST.get('level_ly'),
                "ext": request.POST.get('level_ext')
            },

            "recharge_switch": {
                "dl": request.POST.get('recharge_switch_dl'),
                "ext": request.POST.get('recharge_switch_ext'),
            },
            "assistance": {
                "dl": request.POST.get('assistance_dl'),
                "ext": request.POST.get('assistance_ext'),
            },
            "change_account": {
                "dl": request.POST.get('change_account_dl'),
                "ext": request.POST.get('change_account_ext'),
            },
            "share": {
                "dl": request.POST.get('share_dl'),
                "ext": request.POST.get('share_ext'),
            },
            "update": {
                "dl": request.POST.get('update_dl'),
                "ext": request.POST.get('update_ext'),
            },
            "pkg_name": {
                "dl": request.POST.get('pkg_name_dl'),
                "ext": request.POST.get('pkg_name_ext'),
            },
            "message": {
                "dl": request.POST.get('message_dl'),
                "ext": request.POST.get('message_ext'),
            },
            "gift": {
                "dl": request.POST.get('gift_dl'),
                "ly": request.POST.get('gift_ly'),
                "ext": request.POST.get('gift_ext')
            },
            "define": {
                "yd": request.POST.get('define_yd'),
                "ext": request.POST.get('define_ext')
            },
            "ext": {
                "project_id": request.POST.get('project_id')
            }

        }
        game = get_object_or_404(models.Game, client_id=client_id)
        log_id = request.POST.get('log_id')
        if log_id:
            # 修改log记录
            game_log = TestDetail.objects.filter(id=log_id).update(
                appver=request.POST.get('appver'),
                vcode=request.POST.get('vcode'),
                package=request.POST.get('package'),
                sy_sdk=request.POST.get('sy_sdk'),
                fn_sdk=request.POST.get('fn_sdk'),
                md5=request.POST.get('md5'),
                pt_type=request.POST.get('pt_type'),
                recharge=request.POST.get('recharge'),
                device_id=request.POST.get('device_id'),
                suid=request.POST.get('suid'),
                plat_channel=request.POST.get('plat_channel'),
                sy_channel=request.POST.get('sy_channel'),
                case_info=json.dumps(case_info),
                result=request.POST.get('result'),
                test_ext=request.POST.get('test_ext'),
                creator=request.user.username,
                modify_date=datetime.datetime.now().strftime(
                    '%Y-%m-%d %H:%M:%S')
            )
        else:
            # 新增log记录
            game_log = TestDetail.objects.create(
                game=game,
                appver=request.POST.get('appver'),
                vcode=request.POST.get('vcode'),
                package=request.POST.get('package'),
                sy_sdk=request.POST.get('sy_sdk'),
                fn_sdk=request.POST.get('fn_sdk'),
                md5=request.POST.get('md5'),
                pt_type=request.POST.get('pt_type'),
                recharge=request.POST.get('recharge'),
                device_id=request.POST.get('device_id'),
                plat_channel=request.POST.get('plat_channel'),
                sy_channel=request.POST.get('sy_channel'),
                creator=request.user.username,
                modify_date=datetime.datetime.now().strftime(
                    '%Y-%m-%d %H:%M:%S'),
                result=request.POST.get('result'),
                case_info=json.dumps(case_info),
                test_ext=request.POST.get('test_ext'),
                suid=request.POST.get('suid')

            )

            log_id = game_log.id
        ret = {
            "msg": "OK",
            "log_id": log_id
        }
        return JsonResponse(ret)
    else:
        return HttpResponse('GET OK')


def doc_file(request):
    file_name = request.GET.get('file_name')
    return render(request, 'pkg/doc/' + file_name + '.html')


def get_redis_log(request):
    gameId = request.GET.get("gameId")
    date = request.GET.get("date")
    game_logs = []
    # r = redis.StrictRedis(host='127.0.0.1', port=6379, db=1)
    r = P1.redis_connect()
    if date:
        key = gameId + "_" + date
        count = r.llen(key)
        game_logs = r.lrange(key, 0, count)[::-1]
    else:
        key = gameId + "_20*"
        for key in r.keys(key):
            count = r.llen(key)
            for logs in (r.lrange(key, 0, count)[::-1]):
                game_logs.append(logs)
    return render(request, 'pkg/sdk_log.html', locals())


@accept_websocket
def subscribe(request):
    if not request.is_websocket():  # 判断是不是websocket连接
        try:  # 如果是普通的http方法
            message = request.GET['message']
            return HttpResponse(message)
        except:
            return render(request, 'pkg/subscribe.html')
    else:
        for message in request.websocket:
            r2 = P2.redis_connect()
            p2 = r2.pubsub()
            p2.subscribe(message)
            print("subscribe:",message)
            for item in p2.listen():
                # request.websocket.send(json.dumps(item))  # 发送消息到客户端
                if item['type'] == 'message':
                    data = item['data']
                    request.websocket.send(data)
                    if item['data'] == 'over':
                        break


def get_apk_info(request):
    """ 获取apk包信息"""
    apk_path = request.GET.get("apk_path")
    apk_info = parser_manifest(unzip_apk(apk_path))
    apk_md5 = get_apk_md5(apk_path)
    ret = {
        "msg": "OK",
        "file_path": apk_path,
        "apk_info": apk_info,
        "apk_md5": apk_md5
    }
    return JsonResponse(ret)


def gen_junyu_sign(ts):
    """
    根据传入的时间戳，获取俊雨API的签名md5
    :param ts:
    :return:
    """
    m = hashlib.md5()
    key = "qAcSpKaUc"
    m.update((str(ts) + key).encode("utf-8"))
    return m.hexdigest()


def get_log_junyu_api(plat, os, **kwargs):
    """
    根据俊雨老师提供的api，从服务器中查询埋点日志
    :param plat: 平台，cn：大陆；ly：联运安卓；lyc：联运iOS（未实现）
    :param os: 系统列表，android：安卓；ios：苹果 （ly没有ios，只有lyc有ios）
    :param kwargs:
        kwargs={
            'game':'client_id',
            'osid':'系统类型，1：iOS；2：Android',
            'did':'设备ID',
            'logtype':'日志类型，reg/open/open_before/login/enter2/role/online/online_sdk2/level/pay/pay_game (联运用online_sdk2 大陆用online)',
            'sdkver':'sdk版本号',
            'uid':'uid',
            'platid':'平台ID，大陆默认为1',
            'recdate':'日期%Y%m%d,如20170707',
            'num':'获取行数，前num行',
        }
    :return:
    """

    if not kwargs.get("recdate"):
        kwargs['recdate'] = datetime.datetime.now().strftime('%Y-%m-%d')
    else:
        recdate = str(kwargs['recdate'])
        kwargs['recdate'] = recdate[0:4] + "-" + recdate[4:6] + "-" + recdate[
                                                                      6:8]
    kwargs['ts'] = str(int(time.time()))  # 当前时间戳，如1458099157，5分钟过期，请实时更新接口时间戳
    kwargs['sign'] = gen_junyu_sign(kwargs['ts'])  # 验证字符串，md5(ts+key)
    url = "https://sy.4399houtai.com/%s/%s/api/dataApi/getLogData/" % (plat, os)
    ret = None
    req_url = None
    try:
        req = requests.get(url=url, params=kwargs)
        req_url = req.url
        ret = req.json()
    except Exception as e:
        print(e)
    return ret, req_url


def sdk_api_report(request):
    """ sdk api日志轮询"""
    gameId = request.GET.get("gameId")
    date = request.GET.get("date")
    device_id = request.GET.get("device_id")
    recharge = request.GET.get("recharge")
    regist_dl_result = request.GET.get("regist_dl_result")
    after_login_ly_result = request.GET.get("after_login_ly_result")
    after_login_dl_result = request.GET.get("after_login_dl_result")
    recharge_dl_result = request.GET.get("recharge_dl_result")
    recharge_ly_result = request.GET.get("recharge_ly_result")
    pay_create_result = request.GET.get("paynum_result")
    case_time = request.GET.get("case_time")

    if not date:
        date = str(datetime.datetime.now().strftime("%Y%m%d"))
    if not case_time:
        # 获取当天凌晨时间戳
        case_time = int(time.mktime(time.strptime(
            time.strftime('%Y-%m-%d', time.localtime(time.time())),
            '%Y-%m-%d')))
    if gameId:
        game = get_object_or_404(models.Game, client_id=gameId)
        game_type = game.game_type

        key = gameId + "_" + date

        # 生成redis 日志报告
        udp_report = collections.OrderedDict()
        sy_report = collections.OrderedDict()
        sy_check = ['reg', 'login', ]
        udp_check = ['login']
        if device_id:
            playload = {
                'game': gameId,
                'did': device_id,
                # 'logtype': '日志类型，reg/open/open_before/login/enter2/role/online/online_sdk2/level/pay_game (联运用online_sdk2 大陆用online)',
                # 'platid': '平台ID，大陆默认为1',
                'recdate': date,
                'num': 1,
            }
            if game_type == "android":
                os = "android"
            else:
                os = "ios"
            # 大陆sy 注册日志
            if not regist_dl_result:
                playload['logtype'] = "reg"
                reg_log, req_url = get_log_junyu_api(plat="cn", os=os,
                                                     **playload)
                if reg_log:
                    if reg_log.get("data"):
                        if int(case_time) <= int(
                                reg_log.get("data")[0].get("rectime")):
                            sy_report['reg'] = reg_log.get("data")
                else:
                    sy_report[
                        'reg_error'] = "junyu_api Fail,req_url:%s" % req_url
            # 大陆sy 登录完成日志
            if not after_login_dl_result:
                playload['logtype'] = "login"
                cn_login_log, req_url = get_log_junyu_api(plat="cn", os=os,
                                                          **playload)
                if cn_login_log:
                    if cn_login_log.get("data"):
                        if int(case_time) <= int(
                                cn_login_log.get("data")[0].get("rectime")):
                            sy_report['login'] = cn_login_log.get("data")
                else:
                    sy_report[
                        'login_error'] = "junyu_api Fail,req_url:%s" % req_url
            if recharge:
                sy_check.append("recharge")
                # 大陆sy 充值到游戏日志
                if not recharge_dl_result:
                    playload['logtype'] = "pay_game"
                    cn_recharge_log, req_url = get_log_junyu_api(plat="cn",
                                                                 os=os,
                                                                 **playload)
                    if cn_recharge_log:
                        if cn_recharge_log.get("data"):
                            if int(case_time) <= int(
                                    cn_recharge_log.get("data")[0].get(
                                        "rectime")):
                                sy_report['recharge'] = cn_recharge_log.get(
                                    "data")
                    else:
                        sy_report[
                            'recharge_error'] = "junyu_api Fail,req_url:%s" % req_url

                # 大陆联运ly 充值到游戏日志
                if not recharge_ly_result:
                    playload['logtype'] = "pay_game"
                    ly_recharge_log, req_url = get_log_junyu_api(plat="ly",
                                                                 os=os,
                                                                 **playload)
                    if ly_recharge_log:
                        if ly_recharge_log.get("data"):
                            if int(case_time) <= int(
                                    ly_recharge_log.get("data")[0].get(
                                        "rectime")):
                                udp_report['recharge'] = ly_recharge_log.get(
                                    "data")
                    else:
                        udp_report[
                            'recharge_error'] = "junyu_api Fail,req_url:%s" % req_url

                # 大陆sy 获取订单号
                if not pay_create_result:
                    playload['logtype'] = "pay"
                    cn_paynum_log, req_url = get_log_junyu_api(plat="cn", os=os,
                                                               **playload)
                    if cn_paynum_log:
                        if cn_paynum_log.get("data"):
                            if int(case_time) <= int(
                                    cn_paynum_log.get("data")[0].get(
                                        "rectime")):
                                sy_report['paynum'] = cn_paynum_log.get("data")
                    else:
                        sy_report[
                            'paynum_error'] = "junyu_api Fail,req_url:%s" % req_url

            # 大陆联运ly 登录完成日志
            if not after_login_ly_result:
                playload['logtype'] = "login"
                ly_login_log, req_url = get_log_junyu_api(plat="ly", os=os,
                                                          **playload)
                if ly_login_log:
                    if ly_login_log.get("data"):
                        if int(case_time) <= int(
                                ly_login_log.get("data")[0].get("rectime")):
                            udp_report['login'] = ly_login_log.get("data")
                else:
                    udp_report[
                        'login_error'] = "junyu_api Fail,req_url:%s" % req_url

        report = {"udp_report": udp_report, "sy_report": sy_report,
                  "msg": None}
        sy_action_list = list(sy_report)
        udp_action_list = list(udp_report)
        if set(sy_check).issubset(set(sy_action_list)) and set(
                udp_check).issubset(set(udp_action_list)):
            report["msg"] = "ok"
        udp_report = {}
        sy_report = {}
        return JsonResponse(report)
    else:
        ret = {'msg': "操作失败，gameId为空！"}
        return JsonResponse(ret)


def new_user_setting(request):
    client_id = request.GET.get("client_id")
    is_open = request.GET.get("is_open")
    r = P1.redis_connect()
    key_flag = client_id + "_CHANGE_AUTO_LOGIN"
    if r.exists(key_flag):
        if is_open == "on":
            # 开启开关
            r.set(key_flag, 1)
            code = 1000
            msg = "开关开启成功"
        else:
            # 关闭开关
            r.set(key_flag, 0)
            code = 1001
            msg = "开关关闭成功"
    else:
        r.set(key_flag, 0)
        code = 1002
        msg = "开关已设置关闭"

    ret = {
        "client_id": client_id,
        "is_open": is_open,
        "code": code,
        "msg": msg
    }
    return JsonResponse(ret)


@csrf_exempt
def get_last_version(request):
    """ 获取上一个版本的测试信息，前提条件：版本之间时间差大于一天
    :param request:
    :return:
    """
    game_id = request.GET.get("game_id")
    game = get_object_or_404(models.Game, client_id=game_id)
    ret = {
        "client_id": game_id,
        "appver": "0.0.0.0",
        "vcode": 0
    }
    for detail in TestDetail.objects.filter(game_id=game.id).order_by(
            '-add_date'):
        today = datetime.date.today()
        date_list = detail.add_date.strftime('%Y-%m-%d').split("-")
        date_last = datetime.date(int(date_list[0]), int(date_list[1]),
                                  int(date_list[2]))
        ex_days = (today - date_last).days
        if ex_days > 0:
            appver = detail.appver
            vcode = detail.vcode
            ret = {
                "client_id": game_id,
                "appver": appver,
                "vcode": vcode
            }
            break

    return JsonResponse(ret)


@csrf_exempt
def get_yd_projectid(request):
    game_id = request.GET.get("game_id")
    project_id = request.GET.get("project_id")
    msg = ""
    flag = False
    yd_flag,r_project_id=get_yd_info(game_id)
    if yd_flag:
        if project_id == r_project_id:
            flag = True
        else:
            msg = "project_id校验失败！\n\n当前project_id=%s \n正确project_id=%s\n不匹配，请核查。" % (
                project_id, r_project_id)
    else:
        msg = "project_id校验失败！\n\n该 game_id=%s 在工作台中未配置\n请核实后在工作台中配置" % game_id
    ret = {
        "flag": flag,
        "msg": msg
    }
    return JsonResponse(ret)


def get_yd_api(request):
    import time
    projectid=request.GET.get("projectid")
    time=request.GET.get("time")+"000-"+str(int(time.time()))+"000"
    select='{"gameid":"%s","did":"%s"}'%(request.GET.get("select[gameid]"),request.GET.get("select[did]"))
    # 口袋修仙调试数据
    # time="1523246416000-"+str(int(time.time()))+"000"
    # select='{"gameid":"%s","did":"%s"}'%("1511858350596670","862844035497583")
    returnKey='uid,server,paynum,pt,sourceMoney,payTime,staus,rystatus'
    yd_url="http://www.datacf.com/api/apiData/query"
    req_url=None
    kwargs={
        'projectid':projectid,
        'tid':'MuTBIh0ZMrwLO0O0OBO0O0Om',
        'returnKey':returnKey,
        'time':time,
        'limit':'0-1',
        'select':select
    }
    try:
        req = requests.get(url=yd_url, params=kwargs)
        req_url = req.url
        ret = req.json()
    except Exception as e:
        print(e)
        ret={"msg":"源点api请求失败"}
    print(req_url)
    print(ret)
    return JsonResponse(ret)